@cipher PHOTON256_permutation

sbox uint4[16] s = {12, 5, 6, 11, 9, 0, 10, 13, 3, 14, 15, 8, 4, 7, 1, 2};
pbox uint[64] p = {0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 8, 18, 19, 20, 21, 22, 23, 16, 17, 27, 28, 29, 30, 31, 24, 25, 26, 36, 37, 38, 39, 32, 33, 34, 35, 45, 46, 47, 40, 41, 42, 43, 44, 54, 55, 48, 49, 50, 51, 52, 53, 63, 56, 57, 58, 59, 60, 61, 62};
pboxm uint4[8][8] M = {{2,  4,  2, 11,  2,  8,  5,  6},
                       	{12,  9,  8, 13,  7,  7,  5,  2},
                       	{ 4,  4, 13, 13,  9,  4, 13,  9},
                       	{ 1,  6,  5,  1, 12, 13, 15, 14},
                       	{15, 12,  9, 13, 14,  5, 14, 13},
                       	{ 9, 14,  5, 15,  4, 12,  9, 6},
                       	{12,  2,  2, 10,  3,  1,  1, 14},
                       	{15,  1, 13, 10,  5, 10,  2, 3}};
ffm uint4[16][16] M = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
                      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
                      {0, 2, 4, 6, 8, 10, 12, 14, 3, 1, 7, 5, 11, 9, 15, 13},
                      {0, 3, 6, 5, 12, 15, 10, 9, 11, 8, 13, 14, 7, 4, 1, 2},
                      {0, 4, 8, 12, 3, 7, 11, 15, 6, 2, 14, 10, 5, 1, 13, 9},
                      {0, 5, 10, 15, 7, 2, 13, 8, 14, 11, 4, 1, 9, 12, 3, 6},
                      {0, 6, 12, 10, 11, 13, 7, 1, 5, 3, 9, 15, 14, 8, 2, 4},
                      {0, 7, 14, 9, 15, 8, 1, 6, 13, 10, 3, 4, 2, 5, 12, 11},
                      {0, 8, 3, 11, 6, 14, 5, 13, 12, 4, 15, 7, 10, 2, 9, 1},
                      {0, 9, 1, 8, 2, 11, 3, 10, 4, 13, 5, 12, 6, 15, 7, 14},
                      {0, 10, 7, 13, 14, 4, 9, 3, 15, 5, 8, 2, 1, 11, 6, 12},
                      {0, 11, 5, 14, 10, 1, 15, 4, 7, 12, 2, 9, 13, 6, 8, 3},
                      {0, 12, 11, 7, 5, 9, 14, 2, 10, 6, 1, 13, 15, 3, 4, 8},
                      {0, 13, 9, 4, 1, 12, 8, 5, 2, 15, 11, 6, 3, 14, 10, 7},
                      {0, 14, 15, 1, 13, 3, 2, 12, 9, 7, 6, 8, 4, 10, 11, 5},
                      {0, 15, 13, 2, 9, 6, 4, 11, 1, 14, 12, 3, 8, 7, 5, 10}};

uint4[12] rc = {1, 3, 7, 14, 13, 11, 6, 12, 9, 2, 5, 10};
uint4[8] ic = {0, 1, 3, 7, 15, 14, 12, 8};

r_fn uint4[64] round_function(uint8 r, uint4[8] key, uint4[64] input) {
    #for (i from 0 to 7) {
    #    input[i*8] = input[i*8] ^ rc[r-1] ^ ic[i];
    #}

    uint4[64] s_out;
	for (i from 0 to 63) {
        s_out[i] = s<input[i]>;
	}

    uint4[64] p_out = p<s_out>;

    uint4[64] m_out;
    for (i from 0 to 7) {
        # uint4[8] tx = View(p_out, 0 + i * 8, 7 + i * 8);
        uint4[8] tx = {p_out[i], p_out[i + 8], p_out[i + 16], p_out[i + 24], p_out[i + 32], p_out[i + 40], p_out[i + 48], p_out[i + 56]};
        #uint4[8] tx = {p_out[i*8], p_out[i*8+1], p_out[i*8+2], p_out[i*8+3], p_out[i*8+4], p_out[i*8+5], p_out[i*8+6], p_out[i*8+7]};
        uint4[8] tl_out = M * tx;
        for (j from 0 to 7) {
            #m_out[i+j*8] = tl_out[j];
            m_out[i*8+j] = tl_out[j];
        }
    }
	return m_out;
}

fn uint4[64] enc(uint4[96] key, uint4[64] r_plaintext){
    for (i from 1 to 12) {
        r_plaintext = round_function(i, View(key, (i - 1) * 8, i * 8 - 1), r_plaintext);
    }
    return r_plaintext;
}